package com.ybear.ybutils.utils.notification;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.text.TextUtils;

import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.graphics.drawable.IconCompat;

import com.ybear.ybutils.utils.ObjUtils;
import com.ybear.ybutils.utils.R;
import com.ybear.ybutils.utils.notification.channel.Channel;

import java.util.Arrays;

public class NotificationBuild {
    @IdRes
    private int smallIconResId;
    private IconCompat smallIcon;
    private int smallLevel;
    @IdRes
    private int largeIconResId;
    private Bitmap largeIcon;
    private CharSequence title;
    private CharSequence content;
    private CharSequence ticker;
    private Intent openIntent;
    private Intent deleteIntent;
    private Intent fullScreenIntent;
    private boolean highPriority;
    private boolean autoCancel = true;
    private long when = -1;
    private boolean showWhen;
    @Nullable
    private long[] vibrate;
    private Uri sound = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
    @RequiresApi(api = Build.VERSION_CODES.O)
    private Channel channel;
    
    public NotificationBuild(@NonNull String channelId,
                             @Nullable String channelName,
                             @Importance int importance,
                             boolean isShowBadge) {
        if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ) {
            channel = new Channel( channelId, channelName, importance, isShowBadge );
        }
    }
    public NotificationBuild(@NonNull String channelId, @Nullable String channelName,
                             boolean isShowBadge) {
        this( channelId, channelName, Importance.DEFAULT, isShowBadge );
    }
    public NotificationBuild(@NonNull String channelId, boolean isShowBadge) {
        this( channelId, DefaultChannelName.NOTIFICATION, Importance.DEFAULT, isShowBadge );
    }
    public NotificationBuild(@NonNull String channelId) {
        this( channelId, DefaultChannelName.NOTIFICATION, Importance.DEFAULT, true );
    }

    @NonNull
    @Override
    public String toString() {
        String channelToStr = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && channel != null?
                ", channel=" + channel.toString() :
                "";

        return "NotificationBuild{" +
                "smallIcon=" + smallIcon +
                ", largeIcon=" + largeIcon +
                ", smallLevel=" + smallLevel +
                ", title=" + title +
                ", content=" + content +
                ", ticker=" + ticker +
                ", openIntent=" + openIntent +
                ", deleteIntent=" + deleteIntent +
                ", fullScreenIntent=" + fullScreenIntent +
                ", autoCancel=" + autoCancel +
                ", when=" + when +
                ", showWhen=" + showWhen +
                ", vibrate=" + Arrays.toString( vibrate ) +
                ", sound=" + sound +
                channelToStr +
                '}';
    }

    @Nullable
    private PendingIntent createPendingIntent(Context context, Intent intent) {
        return intent != null ?
                PendingIntent.getActivity( context, 0, intent, 0 ) :
                null;
    }

    @NonNull
    private IconCompat checkIconOfIconCompat(Context context, IconCompat iconCompat) {
        if( iconCompat != null ) return iconCompat;
        return IconCompat.createWithResource( context, getDefaultSmallIconResId() );
    }
    @DrawableRes
    private int checkIconOfResId(int resId) { return resId == 0 ? getDefaultSmallIconResId() : resId; }

    private Bitmap createBitmap(Resources res, @IdRes int resId) {
        return resId == 0 ? null : BitmapFactory.decodeResource( res, resId );
    }
    
    /**
     构建通知Build
     @param context     上下文
     */
    public Notification build(@NonNull Context context) {
        NotificationCompat.Builder b;
        PendingIntent openPending, deletePending, fullScreenPending;
        
        if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ) {
            /* 8.0之后的版本 */
            if( channel == null ) channel = new Channel( ObjUtils.parseString( hashCode() ) );
            b = new NotificationCompat.Builder( context, channel.getChannelId() );
        }else {
            /* 低版本适配 */
            b = new NotificationCompat.Builder( context );
        }
        //小图标
        if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
            b.setSmallIcon( checkIconOfIconCompat( context, smallIcon ) );
        }else {
            int iconResId = checkIconOfResId( smallIconResId );
            if( smallLevel == 0 ) {
                b.setSmallIcon( iconResId );
            }else {
                b.setSmallIcon( iconResId, smallLevel );
            }
        }
        //大图标
        if( largeIcon != null ) {
            b.setLargeIcon( largeIcon );
        }else if( largeIconResId != 0 ) {
            b.setLargeIcon( createBitmap( context.getResources(), largeIconResId ) );
        }

        if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
            b.setSmallIcon( checkIconOfIconCompat( context, smallIcon ) );
        }else {
            int iconResId = checkIconOfResId( smallIconResId );
            if( smallLevel == 0 ) {
                b.setSmallIcon( iconResId );
            }else {
                b.setSmallIcon( iconResId, smallLevel );
            }
        }
        //标题
        if( !TextUtils.isEmpty( title ) ) b.setContentTitle( title );
        //内容
        if( !TextUtils.isEmpty( content ) ) b.setContentText( content );
        //无障碍服务
        if( ticker != null ) b.setTicker( ticker );
        //点击后自动取消
        b.setAutoCancel( autoCancel );
        //时间排序
        if( when > 0 ) b.setWhen( when );
        //是否展示时间
        if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 ) b.setShowWhen( showWhen );
        //震动
        if( vibrate != null ) b.setVibrate( vibrate );

        /* 点击跳转时Intent */
        openPending = createPendingIntent( context, openIntent );
        if( openPending != null ) b.setContentIntent( openPending );
        /* 清除通知时Intent */
        deletePending = createPendingIntent( context, deleteIntent );
        if( deletePending != null ) b.setDeleteIntent( deletePending );
        /* 全屏通知时Intent */
        fullScreenPending = createPendingIntent( context, fullScreenIntent );
        if( fullScreenPending != null ) b.setFullScreenIntent( fullScreenPending, highPriority );

        //提示音
        b.setSound( sound );
        return b.build();
    }

    @DrawableRes
    public int getDefaultSmallIconResId() { return R.drawable.ic_def_notify_small_icon; }

    public IconCompat getSmallIcon() { return smallIcon; }
    @IdRes
    public int getSmallIconResId() {
        if( smallIcon != null ) return smallIcon.getResId();
        return smallIconResId;
    }
    public NotificationBuild setSmallIcon(Bitmap smallIcon) {
        this.smallIcon = IconCompat.createWithBitmap( smallIcon );
        return this;
    }
    public NotificationBuild setSmallIcon(@DrawableRes int smallIcon, int smallLevel) {
        this.smallIconResId = smallIcon;
        this.smallLevel = smallLevel;
        return this;
    }
    public NotificationBuild setSmallIcon(@DrawableRes int smallIcon) {
        return setSmallIcon( smallIcon, 0 );
    }

    public Bitmap getLargeIcon() { return largeIcon; }
    @IdRes
    public int getLargeIconResId() { return largeIconResId; }
    public NotificationBuild setLargeIcon(@Nullable Bitmap largeIcon) {
        this.largeIcon = largeIcon;
        return this;
    }
    public NotificationBuild setLargeIcon(@DrawableRes int resId) {
        largeIconResId = resId;
        return this;
    }

    public CharSequence getTitle() { return title; }
    public NotificationBuild setTitle(CharSequence title) {
        this.title = title;
        return this;
    }

    public CharSequence getContent() { return content; }
    public NotificationBuild setContent(CharSequence content) {
        this.content = content;
        return this;
    }

    public CharSequence getTicker() { return ticker; }
    public NotificationBuild setTicker(CharSequence ticker) {
        this.ticker = ticker;
        return this;
    }

    public Intent getOpenIntent() { return openIntent; }
    public NotificationBuild setOpenIntent(Intent openIntent) {
        this.openIntent = openIntent;
        return this;
    }

    public Intent getDeleteIntent() { return deleteIntent; }
    public NotificationBuild setDeleteIntent(Intent deleteIntent) {
        this.deleteIntent = deleteIntent;
        return this;
    }

    public boolean isHighPriority() { return highPriority; }
    public Intent getFullScreenIntent() { return fullScreenIntent; }
    public NotificationBuild setFullScreenIntent(Intent intent, boolean highPriority) {
        fullScreenIntent = intent;
        this.highPriority = highPriority;
        return this;
    }

    public boolean isAutoCancel() { return autoCancel; }
    public NotificationBuild setAutoCancel(boolean autoCancel) {
        this.autoCancel = autoCancel;
        return this;
    }

    public long getWhen() { return when; }
    public NotificationBuild setWhen(long when) {
        this.when = when;
        return this;
    }

    public boolean isShowWhen() { return showWhen; }
    public NotificationBuild setShowWhen(boolean showWhen) {
        this.showWhen = showWhen;
        return this;
    }

    public long[] getDefaultVibrate() { return new long[] { 0, 500, 1000, 1500 }; }
    @Nullable
    public long[] getVibrate() { return vibrate; }
    public NotificationBuild setVibrate(@Nullable long[] vibrate) {
        this.vibrate = vibrate;
        return this;
    }

    public Uri getSound() { return sound; }
    public NotificationBuild setSound(Uri sound) {
        this.sound = sound;
        return this;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public NotificationBuild setChannel(Channel channel) {
        this.channel = channel;
        return this;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public Channel getChannel() { return channel; }
}
